home *** CD-ROM | disk | FTP | other *** search
- /*
- * Window Maker window manager
- *
- * Copyright (c) 1997, 1998 Alfredo K. Kojima
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
- #include "wconfig.h"
-
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
-
- #ifdef TEXTURE_PLUGIN
- # ifdef HAVE_DLFCN_H
- # include <dlfcn.h>
- # endif
- #endif
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- #include <wraster.h>
-
- #include "WindowMaker.h"
- #include "wcore.h"
- #include "texture.h"
- #include "funcs.h"
-
- extern WPreferences wPreferences;
-
-
- static void bevelImage(RImage *image, int relief);
-
-
-
- WTexSolid*
- wTextureMakeSolid(WScreen *scr, XColor *color)
- {
- WTexSolid *texture;
- int gcm;
- XGCValues gcv;
-
- texture = wmalloc(sizeof(WTexture));
-
- texture->type = WTEX_SOLID;
- texture->subtype = 0;
-
- XAllocColor(dpy, scr->w_colormap, color);
- texture->normal = *color;
- if (color->red==0 && color->blue==0 && color->green == 0) {
- texture->light.red = 0xb6da;
- texture->light.green = 0xb6da;
- texture->light.blue = 0xb6da;
- texture->dim.red = 0x6185;
- texture->dim.green = 0x6185;
- texture->dim.blue = 0x6185;
- } else {
- RColor rgb;
- RHSVColor hsv, hsv2;
- int v;
-
- rgb.red = color->red >> 8;
- rgb.green = color->green >> 8;
- rgb.blue = color->blue >> 8;
- RRGBtoHSV(&rgb, &hsv);
- RHSVtoRGB(&hsv, &rgb);
- hsv2 = hsv;
-
- v = hsv.value*16/10;
- hsv.value = (v > 255 ? 255 : v);
- RHSVtoRGB(&hsv, &rgb);
- texture->light.red = rgb.red << 8;
- texture->light.green = rgb.green << 8;
- texture->light.blue = rgb.blue << 8;
-
- hsv2.value = hsv2.value/2;
- RHSVtoRGB(&hsv2, &rgb);
- texture->dim.red = rgb.red << 8;
- texture->dim.green = rgb.green << 8;
- texture->dim.blue = rgb.blue << 8;
- }
- texture->dark.red = 0;
- texture->dark.green = 0;
- texture->dark.blue = 0;
- XAllocColor(dpy, scr->w_colormap, &texture->light);
- XAllocColor(dpy, scr->w_colormap, &texture->dim);
- XAllocColor(dpy, scr->w_colormap, &texture->dark);
-
- gcm = GCForeground|GCBackground|GCGraphicsExposures;
- gcv.graphics_exposures = False;
-
- gcv.background = gcv.foreground = texture->light.pixel;
- texture->light_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
-
- gcv.background = gcv.foreground = texture->dim.pixel;
- texture->dim_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
-
- gcv.background = gcv.foreground = texture->dark.pixel;
- texture->dark_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
-
- gcv.background = gcv.foreground = color->pixel;
- texture->normal_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
-
- return texture;
- }
-
-
- static int
- dummyErrorHandler(Display *foo, XErrorEvent *bar)
- {
- #ifdef DEBUG
- wwarning("your server is buggy. Tell the author if some error related to color occurs");
- #endif
- return 0;
- }
-
-
- void
- wTextureDestroy(WScreen *scr, WTexture *texture)
- {
- int i;
- int count=0;
- unsigned long colors[8];
-
- #ifdef DEBUG
- if (texture==NULL) {
- printf("BUG: trying to free NULL texture\n");
- return;
- }
- #endif
-
- /*
- * some stupid servers don't like white or black being freed...
- */
- #define CANFREE(c) (c!=scr->black_pixel && c!=scr->white_pixel && c!=0)
- switch (texture->any.type) {
- case WTEX_SOLID:
- XFreeGC(dpy, texture->solid.light_gc);
- XFreeGC(dpy, texture->solid.dark_gc);
- XFreeGC(dpy, texture->solid.dim_gc);
- if (CANFREE(texture->solid.light.pixel))
- colors[count++] = texture->solid.light.pixel;
- if (CANFREE(texture->solid.dim.pixel))
- colors[count++] = texture->solid.dim.pixel;
- if (CANFREE(texture->solid.dark.pixel))
- colors[count++] = texture->solid.dark.pixel;
- break;
-
- case WTEX_PIXMAP:
- RDestroyImage(texture->pixmap.pixmap);
- break;
-
- case WTEX_MHGRADIENT:
- case WTEX_MVGRADIENT:
- case WTEX_MDGRADIENT:
- for (i=0; texture->mgradient.colors[i]!=NULL; i++) {
- free(texture->mgradient.colors[i]);
- }
- free(texture->mgradient.colors);
- break;
-
- case WTEX_THGRADIENT:
- case WTEX_TVGRADIENT:
- case WTEX_TDGRADIENT:
- RDestroyImage(texture->tgradient.pixmap);
- break;
-
- #ifdef TEXTURE_PLUGIN
- case WTEX_FUNCTION:
- #ifdef HAVE_DLFCN_H
- if (texture->function.handle) {
- dlclose(texture->function.handle);
- }
- #endif
- for (i = 0; i < texture->function.argc; i++) {
- free(texture->function.argv[i]);
- }
- free(texture->function.argv);
- break;
- #endif /* TEXTURE_PLUGIN */
- }
- if (CANFREE(texture->any.color.pixel))
- colors[count++] = texture->any.color.pixel;
- if (count > 0) {
- XErrorHandler oldhandler;
-
- /* ignore error from buggy servers that don't know how
- * to do reference counting for colors. */
- XSync(dpy,0);
- oldhandler = XSetErrorHandler(dummyErrorHandler);
- XFreeColors(dpy, scr->w_colormap, colors, count, 0);
- XSync(dpy,0);
- XSetErrorHandler(oldhandler);
- }
- XFreeGC(dpy, texture->any.gc);
- free(texture);
- #undef CANFREE
- }
-
-
-
- WTexGradient*
- wTextureMakeGradient(WScreen *scr, int style, RColor *from, RColor *to)
- {
- WTexGradient *texture;
- XGCValues gcv;
-
-
- texture = wmalloc(sizeof(WTexture));
- memset(texture, 0, sizeof(WTexture));
- texture->type = style;
- texture->subtype = 0;
-
- texture->color1 = *from;
- texture->color2 = *to;
-
- texture->normal.red = (from->red + to->red)<<7;
- texture->normal.green = (from->green + to->green)<<7;
- texture->normal.blue = (from->blue + to->blue)<<7;
-
- XAllocColor(dpy, scr->w_colormap, &texture->normal);
- gcv.background = gcv.foreground = texture->normal.pixel;
- gcv.graphics_exposures = False;
- texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
- |GCGraphicsExposures, &gcv);
-
- return texture;
- }
-
-
-
- WTexMGradient*
- wTextureMakeMGradient(WScreen *scr, int style, RColor **colors)
- {
- WTexMGradient *texture;
- XGCValues gcv;
- int i;
-
-
- texture = wmalloc(sizeof(WTexture));
- memset(texture, 0, sizeof(WTexture));
- texture->type = style;
- texture->subtype = 0;
-
- i=0;
- while (colors[i]!=NULL) i++;
- i--;
- texture->normal.red = (colors[0]->red<<8);
- texture->normal.green = (colors[0]->green<<8);
- texture->normal.blue = (colors[0]->blue<<8);
-
- texture->colors = colors;
-
- XAllocColor(dpy, scr->w_colormap, &texture->normal);
- gcv.background = gcv.foreground = texture->normal.pixel;
- gcv.graphics_exposures = False;
- texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
- |GCGraphicsExposures, &gcv);
-
- return texture;
- }
-
-
-
- WTexPixmap*
- wTextureMakePixmap(WScreen *scr, int style, char *pixmap_file, XColor *color)
- {
- WTexPixmap *texture;
- XGCValues gcv;
- RImage *image;
- char *file;
-
- file = FindImage(wPreferences.pixmap_path, pixmap_file);
- if (!file) {
- wwarning(_("image file \"%s\" used as texture could not be found."),
- pixmap_file);
- return NULL;
- }
- image = RLoadImage(scr->rcontext, file, 0);
- if (!image) {
- wwarning(_("could not load texture pixmap \"%s\":%s"), file,
- RMessageForError(RErrorCode));
- free(file);
- return NULL;
- }
- free(file);
-
- texture = wmalloc(sizeof(WTexture));
- memset(texture, 0, sizeof(WTexture));
- texture->type = WTEX_PIXMAP;
- texture->subtype = style;
-
- texture->normal = *color;
-
- XAllocColor(dpy, scr->w_colormap, &texture->normal);
- gcv.background = gcv.foreground = texture->normal.pixel;
- gcv.graphics_exposures = False;
- texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
- |GCGraphicsExposures, &gcv);
-
- texture->pixmap = image;
-
- return texture;
- }
-
-
-
- WTexTGradient*
- wTextureMakeTGradient(WScreen *scr, int style, RColor *from, RColor *to,
- char *pixmap_file, int opacity)
- {
- WTexTGradient *texture;
- XGCValues gcv;
- RImage *image;
- char *file;
-
- file = FindImage(wPreferences.pixmap_path, pixmap_file);
- if (!file) {
- wwarning(_("image file \"%s\" used as texture could not be found."),
- pixmap_file);
- return NULL;
- }
- image = RLoadImage(scr->rcontext, file, 0);
- if (!image) {
- wwarning(_("could not load texture pixmap \"%s\":%s"), file,
- RMessageForError(RErrorCode));
- free(file);
- return NULL;
- }
- free(file);
-
- texture = wmalloc(sizeof(WTexture));
- memset(texture, 0, sizeof(WTexture));
- texture->type = style;
-
- texture->opacity = opacity;
-
- texture->color1 = *from;
- texture->color2 = *to;
-
- texture->normal.red = (from->red + to->red)<<7;
- texture->normal.green = (from->green + to->green)<<7;
- texture->normal.blue = (from->blue + to->blue)<<7;
-
- XAllocColor(dpy, scr->w_colormap, &texture->normal);
- gcv.background = gcv.foreground = texture->normal.pixel;
- gcv.graphics_exposures = False;
- texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
- |GCGraphicsExposures, &gcv);
-
- texture->pixmap = image;
-
- return texture;
- }
-
-
- #ifdef TEXTURE_PLUGIN
- WTexFunction*
- wTextureMakeFunction(WScreen *scr, char *lib, char *func, int argc, char **argv)
- {
- XColor fallbackColor;
- XGCValues gcv;
- WTexFunction *texture;
-
- texture = wmalloc(sizeof(WTexture));
- texture->type = WTEX_FUNCTION;
- texture->handle = NULL;
- texture->render = 0;
- texture->argc = argc;
- texture->argv = argv;
-
- fallbackColor.red = 0x8000;
- fallbackColor.green = 0x8000;
- fallbackColor.blue = 0x8000;
-
- gcv.background = gcv.foreground = fallbackColor.pixel;
- gcv.graphics_exposures = False;
- texture->normal_gc = XCreateGC(dpy, scr->w_win, GCForeground|GCBackground
- |GCGraphicsExposures, &gcv);
-
- # ifdef HAVE_DLFCN_H
- /* open the library */
- texture->handle = dlopen(lib, RTLD_LAZY);
- if (!texture->handle) {
- wwarning(_("library \"%s\" cound not be opened."), lib);
- free(argv);
- free(texture);
- return NULL;
- }
-
- /* find the function */
- texture->render = dlsym(texture->handle, func);
- if (!texture->render) {
- wwarning(_("function \"%s\" not found in library \"%s\""), func, lib);
- free(argv);
- dlclose(texture->handle);
- free(texture);
- return NULL;
- }
- # else
- wwarning(_("function textures not supported on this system, sorry."));
- # endif
-
- /* success! */
- return texture;
- }
- #endif /* TEXTURE_PLUGIN */
-
-
- RImage*
- wTextureRenderImage(WTexture *texture, int width, int height,
- int relief)
- {
- RImage *image = NULL;
- RColor color1;
- int d;
- int subtype;
-
- switch (texture->any.type) {
- case WTEX_SOLID:
- image = RCreateImage(width, height, False);
-
- color1.red = texture->solid.normal.red >> 8;
- color1.green = texture->solid.normal.green >> 8;
- color1.blue = texture->solid.normal.blue >> 8;
- color1.alpha = 255;
-
- RClearImage(image, &color1);
- break;
-
- case WTEX_PIXMAP:
- if (texture->pixmap.subtype == WTP_TILE) {
- image = RMakeTiledImage(texture->pixmap.pixmap, width, height);
- } else if (texture->pixmap.subtype == WTP_CENTER) {
- color1.red = texture->pixmap.normal.red>>8;
- color1.green = texture->pixmap.normal.green>>8;
- color1.blue = texture->pixmap.normal.blue>>8;
- color1.alpha = 255;
- image = RMakeCenteredImage(texture->pixmap.pixmap, width, height,
- &color1);
- } else {
- image = RScaleImage(texture->pixmap.pixmap, width, height);
- }
- break;
-
- case WTEX_HGRADIENT:
- subtype = RGRD_HORIZONTAL;
- goto render_gradient;
-
- case WTEX_VGRADIENT:
- subtype = RGRD_VERTICAL;
- goto render_gradient;
-
- case WTEX_DGRADIENT:
- subtype = RGRD_DIAGONAL;
- render_gradient:
-
- image = RRenderGradient(width, height, &texture->gradient.color1,
- &texture->gradient.color2, subtype);
- break;
-
- case WTEX_MHGRADIENT:
- subtype = RGRD_HORIZONTAL;
- goto render_mgradient;
-
- case WTEX_MVGRADIENT:
- subtype = RGRD_VERTICAL;
- goto render_mgradient;
-
- case WTEX_MDGRADIENT:
- subtype = RGRD_DIAGONAL;
- render_mgradient:
- image = RRenderMultiGradient(width, height,
- &(texture->mgradient.colors[1]),
- subtype);
- break;
-
- case WTEX_THGRADIENT:
- subtype = RGRD_HORIZONTAL;
- goto render_tgradient;
-
- case WTEX_TVGRADIENT:
- subtype = RGRD_VERTICAL;
- goto render_tgradient;
-
- case WTEX_TDGRADIENT:
- subtype = RGRD_DIAGONAL;
- render_tgradient:
- {
- RImage *grad;
-
- image = RMakeTiledImage(texture->tgradient.pixmap, width, height);
- if (!image)
- break;
-
- grad = RRenderGradient(width, height, &texture->tgradient.color1,
- &texture->tgradient.color2, subtype);
- if (!grad) {
- RDestroyImage(image);
- image = NULL;
- break;
- }
-
- RCombineImagesWithOpaqueness(image, grad,
- texture->tgradient.opacity);
- RDestroyImage(grad);
- }
- break;
-
- #ifdef TEXTURE_PLUGIN
- case WTEX_FUNCTION:
- #ifdef HAVE_DLFCN_H
- if (texture->function.render) {
- image = texture->function.render (
- texture->function.argc, texture->function.argv,
- width, height, relief);
- }
- #endif
- if (!image) {
- RErrorCode = RERR_INTERNAL;
- }
- break;
- #endif /* TEXTURE_PLUGIN */
-
- default:
- puts("ERROR in wTextureRenderImage()");
- image = NULL;
- break;
- }
-
- if (!image) {
- RColor gray;
-
- wwarning(_("could not render texture: %s"), RMessageForError(RErrorCode));
-
- image = RCreateImage(width, height, False);
-
- gray.red = 190;
- gray.green = 190;
- gray.blue = 190;
- gray.alpha = 255;
- RClearImage(image, &gray);
- }
-
-
- /* render bevel */
-
- switch (relief) {
- case WREL_ICON:
- d = RBEV_RAISED3;
- break;
-
- case WREL_RAISED:
- d = RBEV_RAISED2;
- break;
-
- case WREL_SUNKEN:
- d = RBEV_SUNKEN;
- break;
-
- case WREL_FLAT:
- d = 0;
- break;
-
- case WREL_MENUENTRY:
- d = -WREL_MENUENTRY;
- break;
-
- default:
- d = 0;
- }
-
- if (d > 0) {
- RBevelImage(image, d);
- } else if (d < 0) {
- bevelImage(image, -d);
- }
-
- return image;
- }
-
-
-
- static void
- bevelImage(RImage *image, int relief)
- {
- int width = image->width;
- int height = image->height;
- RColor color;
-
- switch (relief) {
- case WREL_MENUENTRY:
- color.red = color.green = color.blue = 80;
- color.alpha = 0;
- /**/
- ROperateLine(image, RAddOperation, 1, 0, width-2, 0, &color);
- /**/
-
- ROperateLine(image, RAddOperation, 0, 0, 0, height-1, &color);
-
- color.red = color.green = color.blue = 40;
- color.alpha = 0;
- ROperateLine(image, RSubtractOperation, width-1, 0, width-1,
- height-1, &color);
-
- /**/
- ROperateLine(image, RSubtractOperation, 1, height-2, width-2,
- height-2, &color);
-
- color.red = color.green = color.blue = 0;
- color.alpha = 255;
- RDrawLine(image, 0, height-1, width-1, height-1, &color);
- /**/
- break;
-
- }
- }
-
-
-
- void
- wDrawBevel(Drawable d, unsigned width, unsigned height,
- WTexSolid *texture, int relief)
- {
- GC light, dim, dark;
- XSegment segs[4];
-
- if (relief==WREL_FLAT) return;
-
- light = texture->light_gc;
- dim = texture->dim_gc;
- dark = texture->dark_gc;
- switch (relief) {
- case WREL_FLAT:
- return;
- case WREL_MENUENTRY:
- case WREL_RAISED:
- case WREL_ICON:
- segs[0].x1 = 1;
- segs[0].x2 = width - 2;
- segs[0].y2 = segs[0].y1 = height - 2;
- segs[1].x1 = width - 2;
- segs[1].y1 = 1;
- segs[1].x2 = width - 2;
- segs[1].y2 = height - 2;
- XDrawSegments(dpy, d, dim, segs, 2);
- segs[0].x1 = 0;
- segs[0].x2 = width - 1;
- segs[0].y2 = segs[0].y1 = height - 1;
- segs[1].x1 = segs[1].x2 = width - 1;
- segs[1].y1 = 0;
- segs[1].y2 = height - 1;
- XDrawSegments(dpy, d, dark, segs, 2);
- segs[0].x1 = segs[0].y1 = segs[0].y2 = 0;
- segs[0].x2 = width - 2;
- segs[1].x1 = segs[1].y1 = 0;
- segs[1].x2 = 0;
- segs[1].y2 = height - 2;
- XDrawSegments(dpy, d, light, segs, 2);
- if (relief==WREL_ICON) {
- segs[0].x1 = segs[0].y1 = segs[0].y2 = 1;
- segs[0].x2 = width - 2;
- segs[1].x1 = segs[1].y1 = 1;
- segs[1].x2 = 1;
- segs[1].y2 = height - 2;
- XDrawSegments(dpy, d, light, segs, 2);
- }
- break;
- #ifdef unused
- case WREL_SUNKEN:
- segs[0].x1 = 0;
- segs[0].x2 = width - 1;
- segs[0].y2 = segs[0].y1 = 0;
- segs[1].x1 = segs[1].x2 = 0;
- segs[1].y1 = 0;
- segs[1].y2 = height - 1;
- XDrawSegments(dpy, d, dark, segs, 2);
-
- segs[0].x1 = 0;
- segs[0].y1 = segs[0].y2 = height - 1;
- segs[0].x2 = width - 1;
- segs[1].x2 = segs[1].x1 = width - 1;
- segs[1].y1 = 1;
- segs[1].y2 = height - 1;
- XDrawSegments(dpy, d, light, segs, 2);
- break;
- #endif
- }
- }
-
-